package cn.justforchris.blog.service.impl;


import cn.justforchris.blog.domain.Address;
import cn.justforchris.blog.domain.Article;
import cn.justforchris.blog.dto.ArticleDto;
import cn.justforchris.blog.mapper.ArticleMapper;
import cn.justforchris.blog.mapper.IpAddressMapper;
import cn.justforchris.blog.query.articleQuery;
import cn.justforchris.blog.service.IArticleService;
import cn.justforchris.util.JsonResult;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletRequest;
import java.util.*;

/**
 * 文章服务实现类
 */
@Service
@Slf4j
@Transactional(readOnly = true,propagation = Propagation.SUPPORTS)  /*业务逻辑*/
@CacheConfig(cacheNames = "ArticleType")    /*缓存名称*/
public class ArticleServiceImpl implements IArticleService {

    @Autowired
    private ArticleMapper articleMapper;

    @Autowired
    private IpAddressMapper ipAddressMapper;



    @Autowired//只能用指定的API
    private MongoTemplate template;
    /*MongoDB的API,用于调用MongoDB数据库*/

    /**
     * 插入文章,也将其放入Mongodb
     * @param article
     */
    @Override
    @Transactional
    public void insertArticle(Article article) {
        Date date = new Date();
        article.setCreateTime(date);
        articleMapper.insertArticle(article);
        template.save(article);
    }

    /**
     * 删除文章,也将其从Mongodb中删除
     * @param id
     */
    @Override
    @Transactional
    public void deleteArticle(Long id) {
        articleMapper.deleteArticle(id);
        /*query是MongoDB的API,用于设定查询条件*/
        Query query = new Query(Criteria.where("id").is(id));
        /*remove是MongoDB的API,用于删除数据,query是删除的条件,Article是要删除的数据的类型*/
        template.remove(query, Article.class);
    }

    /**
     * 批量删除文章,也将其从Mongodb中删除
     * @param ids
     */
    @Override
    public void patchDelete(Long[] ids) {
        articleMapper.patchDelete(ids);
        for (Long id : ids) {
            Query query = new Query(Criteria.where("id").is(id));
            template.remove(query, Article.class);
        }
    }

    /**
     * 更新文章,也将其更新到Mongodb中,这里是根据文章的id获取MongoDB中文章的_id,然后更新,MongoDB的_id是唯一的,id只是其中
     * 的一个字段
     * @param article
     */
    @Override
    @Transactional
    public void updateArticle(Article article) {
        articleMapper.updateArticle(article);
        Query query = new Query(Criteria.where("id").is(article.getId()));
        Article one = template.findOne(query, Article.class);
        article.set_id(one.get_id());
        template.save(article);
    }

    /**
     * 根据id获取文章
     * @param id
     * @return
     */
    @Override
    public Article getArticleById(Long id) {
        return articleMapper.getArticleById(id);
    }

    /**
     * 获取所有文章
     * @return
     */
    @Override
    public List<Article> getAll() {
        return articleMapper.getAll();
    }

    /**
     * 分页查询文章
     * @param queryPage
     * @return
     */
    @Override
    public PageInfo<Article> queryPage(articleQuery queryPage) {
        PageHelper.startPage(queryPage.getCurrentPage(),queryPage.getPageSize());
        List<Article> data = articleMapper.queryPage(queryPage);
        /*
        这里获取到的是符合传入参数currentpage和pagesize的数据,也就是说,如果不传pagesize就只有五条因为怕个size如果不传入的话就是5
        但是如果有pagesize传入就根据传入数据来
        */
        return new PageInfo<>(data);
        /*这里面就包含了pagehelper帮忙计算出来的total(总共多少条,和根据分页提取出的数据)*/

    }

    /**
     * 根据文章类型获取每个类型文章数量
     * @return
     */
    @Override
    public List<ArticleDto> countByArticleType() {
        return articleMapper.countByArticleType();
    }

    /**
     * 根据日期获取每个日期的文章数量
     * @return
     */
    @Override
    public List<ArticleDto> countByDate() {
        return articleMapper.countByDate();
    }

    /**
     * 获取相关文章,也就是文章标签相同的文章
     * @param id
     * @return
     */
    @Override
    public List<Article> getRelated(Long id) {
        return  articleMapper.getRelated(id);
    }

    @Override
    public List<Article> getarticleByYear(String time) {

//        if (year=="9999-"){

            return articleMapper.getarticleByYear(time);
//        }
//        return articleMapper.getarticleByYear(year);
    }

    @Override
    public List<ArticleDto> countByDateAndYear(String year) {
        return articleMapper.countByDateAndYear(year);
    }

    @Override
    public List<ArticleDto> orderByStar() {
        return articleMapper.orderByStar();
    }

    @Override
    public List<ArticleDto> orderByNum() {
        return articleMapper.orderByNum();
    }

    @Override
    public void addReadCount(Long id) {
        articleMapper.addReadCount(id);
    }





    @Override
    public JsonResult updateStar(Long id, HttpServletRequest request) {
        List<String> address = ipAddressMapper.findByArticleId(id);
        String ip = request.getRemoteAddr();
        if (address.contains(ip)){//数据库有ip地址 - 以前点赞了 - 再点就是取消点赞
            ipAddressMapper.delByIpAndArticleId(ip,id);
            articleMapper.decreStar(id);
            return JsonResult.success("cancel");
        }else {
            Address ipAddress = new Address();
            ipAddress.setAddress(ip);
            ipAddress.setArticleId(id);
            Date date = new Date();
            ipAddress.setCreateTime(date);
            ipAddressMapper.add(ipAddress);
            articleMapper.increStar(id);
            return JsonResult.success("star");
        }
    }

    @Override
    public JsonResult initIconClass(Long id, HttpServletRequest request) {
        List<String> ips = ipAddressMapper.findByArticleId(id);
        String ip = request.getRemoteAddr();
        if (ips.contains(ip)){//数据库有mac地址 - 以前点赞过 - 再点就是取消点赞
            return JsonResult.success("ok");
        }else {
            return JsonResult.success("no");
        }
    }

    @Override
    public List<Article> getArticleByType(Long id) {
        return articleMapper.getArticleByType(id);
    }

    @Override
    public List<String> getYears(String year) {
        if(year.equals("99999")){
            List<String> allYears = new ArrayList<>();
            for (String Year : articleMapper.getAllYears()) {
                allYears.add(Year.substring(0,4));

            }
            return allYears;
        }else{
            List<String> allTimes = new ArrayList<>();
            for (String articleMapperYear : articleMapper.getYears(year)) {
                allTimes.add(articleMapperYear.substring(0,4));
            }


            return allTimes;
        }

    }


}
